home *** CD-ROM | disk | FTP | other *** search
- /* NeXT_obuffer.cc
-
- Output buffer for NeXTStep copied from maplay 1.3b */
-
- /*
- * @(#) obuffer_next.cc 1.1, last edit: 27 Oct 1994 17:20:53
- * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
- * @(#) Berlin University of Technology
- *
- * NeXTStep class written at the end of June 1994 by
- * Pete French (pete@ohm.york.ac.uk) and Ian Stepehnson (ian@ohm.york.ac.uk)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
- * New in maplay 1.3
- */
-
- // This code is messy. I'm not proud of it, but it does work.
- // Bear in mind that it is multi-threaded or it will make no
- // sense whatsoever. I apologise to any C++ programmers. All
- // the C++ I know was learnt from reading these files. Hence
- // it bears a striking resemblance to the Linux code...
- //
- // -Pete French.
-
- #ifdef NeXT
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/ioctl.h>
- #include <iostream.h>
-
- #include "args.h"
- #include "header.h"
- #include "obuffer.h"
-
- extern "Objective-C" {
- #import <appkit/appkit.h>
- #import <soundkit/NXPlayStream.h>
- #import <soundkit/NXSoundOut.h>
- #import <machkit/NXLock.h>
- };
-
- float NeXTObuffer::sample_rate;
- int NeXTObuffer::chans;
-
- extern char *next_sound_host; // from -H argument
-
- static id song_lock_id, queue_lock_id;
- static id device_id, player_id;
- static int queue_length, drain_queue;
-
-
- @interface queue_counter:Object
- {
- }
- - soundStream:sender didCompleteBuffer:(int)tag;
- @end
-
-
- @implementation queue_counter
- - soundStream:sender didCompleteBuffer:(int)tag
- {
- [queue_lock_id lock];
- queue_length--;
- if(queue_length>MAX_QUEUE_LENGTH)
- [queue_lock_id unlockWith:CANNOT_QUEUE];
- else
- [queue_lock_id unlockWith:CAN_QUEUE];
- if((drain_queue) && (queue_length==0))
- [song_lock_id unlock];
- return self;
- }
- @end
-
-
- NeXTObuffer::NeXTObuffer (uint32 number_of_channels, MPEG_Args *maplay_args)
- {
- #ifdef DEBUG
- if (!number_of_channels || number_of_channels > MAXCHANNELS)
- {
- cerr << "NeXTObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
- exit (1);
- }
- #endif
- sample_rate=(float)maplay_args->MPEGheader->frequency();
- chans=number_of_channels;
- if((sample_rate!=SND_RATE_HIGH) && (sample_rate!=SND_RATE_LOW))
- {
- cerr << "NeXT cannot play at sample rate " << sample_rate << "\n";
- exit (1);
- }
- for (int i = 0; i < number_of_channels; ++i)
- bufferp[i] = buffer + i;
-
- // get a device and player
- device_id=[NXSoundOut alloc];
- player_id=[NXPlayStream alloc];
-
- // initialise device and attach to player
- if(next_sound_host!=NULL)
- {
- if([device_id initOnHost:next_sound_host]==nil)
- {
- cerr << "Could not get sound device on " << next_sound_host << "\n";
- exit(1);
- }
- }
- else
- [device_id init];
- [player_id initOnDevice:device_id];
-
- // setup the queue and queue counter
- queue_lock_id=[[NXConditionLock alloc] initWith:CAN_QUEUE];
- queue_length=0;
- drain_queue=0;
- [player_id setDelegate:[[queue_counter alloc] init]];
-
- //and start the player
- song_lock_id=[[NXLock alloc] init];
- [song_lock_id lock];
- [player_id activate];
- }
-
-
- void NeXTObuffer::really_write_buffer (int16 **bp, int16 *bf)
- {
- int length = (int)((char *)bp[0] - (char *)bf);
- [queue_lock_id lockWhen:CAN_QUEUE];
- queue_length++;
- if(queue_length>MAX_QUEUE_LENGTH)
- [queue_lock_id unlockWith:CANNOT_QUEUE];
- else
- [queue_lock_id unlockWith:CAN_QUEUE];
- [player_id playBuffer:bf
- size:length
- tag:(int)1
- channelCount:chans
- samplingRate:sample_rate];
- for (int i = 0; i < chans; ++i)
- bp[i] = bf + i;
- }
-
-
- NeXTObuffer::~NeXTObuffer (void)
- {
- NeXTObuffer::really_write_buffer(bufferp,buffer);
- drain_queue=1;
- [song_lock_id lock];
- }
-
-
- void NeXTObuffer::append (uint32 channel, int16 value)
- {
- #ifdef DEBUG
- if (channel >= chans)
- {
- cerr << "illegal channelnumber in NeXTObuffer::append()!\n";
- exit (1);
- }
- #endif
- if (bufferp[channel] - buffer >= OBUFFERSIZE)
- NeXTObuffer::really_write_buffer(bufferp,buffer);
- *bufferp[channel] = htons(value);
- bufferp[channel] += chans;
- }
-
- #ifdef SEEK_STOP
- void NeXTObuffer::clear_buffer(void)
- {
- }
-
- void NeXTObuffer::set_stop_flag(void)
- {
- }
- #endif // SEEK_STOP
-
- Obuffer *create_obuffer(MPEG_Args *maplay_args)
- {
- Obuffer *buffer;
-
- enum e_mode mode = maplay_args->MPEGheader->mode();
- enum e_channels which_channels = maplay_args->which_c;
-
- if (mode == single_channel || which_channels != both)
- buffer = new NeXTObuffer (1, maplay_args);
- else
- buffer = new NeXTObuffer (2, maplay_args);
-
- return(buffer);
- }
-
- #endif // NeXT
-